package com.his.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.his.dao.domain.dto.ListDto;
import com.his.dao.domain.entity.MInterface;
import com.his.dao.domain.entity.Role;
import com.his.dao.domain.entity.User;
import com.his.dao.domain.vo.ListVo;
import com.his.dao.domain.vo.LoginVo;
import com.his.dao.mapper.UserMapper;
import com.his.admin.service.UserService;
import com.his.util.constant.RedisConstant;
import com.his.util.result.RestResult;
import com.his.util.result.RestResultBuilder;
import com.his.util.result.ResultCode;
import com.his.util.util.IpUtil;
import com.his.util.util.MapUtil;
import com.his.util.util.StringUtil;
import com.his.util.util.TokenUtil;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.concurrent.TimeUnit;

import static com.his.util.constant.RedisConstant.*;

@Service
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private RedisTemplate redisTemplate;
    private UserMapper userMapper;

    @Override
    public RestResult login(HttpServletRequest request, User user) {
        if (user.getUsername() == null || user.getPassword() == null) {
            return new RestResultBuilder().fail(ResultCode.ERROR_ACCOUNT_PASSWORD);
        }

        QueryWrapper<User> queryWrapper = new QueryWrapper<User>()
                .eq("username", user.getUsername())
                .eq("password", user.getPassword());

        user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            return new RestResultBuilder().fail(ResultCode.ERROR_ACCOUNT_PASSWORD);
        }

        user.setLoginIp(IpUtil.getIpAddr(request));
        user.setLoginTime(LocalDateTime.now());
        updateById(user);

        String authorization = TokenUtil.getInstance().makeToken();

        // 存放用户token
        redisTemplate.opsForValue().set(REDIS_FOLDER + USER + user.getUserId(), authorization, 1, TimeUnit.HOURS);
        // 存放用户id
        redisTemplate.opsForValue().set(getUserAndAuthorization(authorization), USER + user.getUserId(), 1, TimeUnit.HOURS);
        // 存放用户角色权限
        redisTemplate.opsForValue().set(getRoleAndAuthorization(authorization), ROLE + user.getRoleId(), 1, TimeUnit.HOURS);
        // 存放医院 id
        redisTemplate.opsForValue().set(getHospitalAndAuthorization(authorization), HOSPITAL+user.getHospitalId(), 1, TimeUnit.HOURS);

        return new RestResultBuilder().success(LoginVo
                .builder()
                .userId(user.getUserId())
                .authorization(authorization)
                .hospitalId(user.getHospitalId())
                .build());
    }

    @Override
    public RestResult logon(String authorization) {
        String userId = (String) redisTemplate.opsForValue().get(RedisConstant.REDIS_FOLDER + authorization);
        redisTemplate.delete(RedisConstant.REDIS_FOLDER + authorization);
        redisTemplate.delete(RedisConstant.REDIS_FOLDER + userId);

        return new RestResultBuilder().success();
    }

    @Override
    public RestResult userInfo(String authorization) {
        int userId = StringUtil.getId(RedisConstant.USER, (String) redisTemplate.opsForValue().get(getUserAndAuthorization(authorization)));

        QueryWrapper<User> queryWrapper = new QueryWrapper<User>()
                .select("name")
                .eq("user_id", userId);

        User user = userMapper.selectOne(queryWrapper);

        return new RestResultBuilder().success(user);
    }

    @Override
    public RestResult all(String authorization, ListDto listDto) {
        User user = MapUtil.conversionMapToObj((LinkedHashMap) listDto.getObj(), User.class);

        return new RestResultBuilder().success(ListVo
                .builder()
                .list(userMapper.selectAll(
                        user.getName(),
                        user.getUsername(),
                        user.getSectionId(),
                        user.getRoleId(),
                        user.getHospitalId(),
                        listDto.getPage() * listDto.getPageSize(),
                        listDto.getPageSize()))
                .total(userMapper.selectAllCount(user.getName(),
                        user.getUsername(),
                        user.getSectionId(),
                        user.getRoleId(),
                        user.getHospitalId()))
                .build());
    }

    @Override
    public RestResult allId(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>()
                .select("user_id", "name")
                .eq(user.getHospitalId() != null && user.getHospitalId() != 0, "hospital_id", user.getHospitalId())
                .eq(user.getSectionId() != null && user.getSectionId() != 0, "section_id", user.getSectionId())
                .eq(user.getRoleId() != null,"role_id", user.getRoleId())
                .like(user.getName() != null, "name", user.getName());
        return new RestResultBuilder().success(userMapper.selectList(queryWrapper));
    }

    @Override
    public RestResult allScheduleId(User user) {
        return new RestResultBuilder().success(userMapper.allScheduleId(user.getSectionId()));
    }
}
